package org.aldar.bquest.logic.controller.board;

import android.util.Log;
import org.aldar.bquest.constants.IConstants;
import org.aldar.bquest.entity.AbilityTileSprite;
import org.aldar.bquest.entity.TileSprite;
import org.aldar.bquest.entity.TileSpriteUtil;
import org.aldar.bquest.entity.pool.TilesPool;
import org.aldar.bquest.logic.controller.entity.TileBoard;
import org.aldar.bquest.logic.layout.ScreenContentManager;
import org.aldar.bquest.resources.ResourceManager;
import org.aldar.bquest.screens.MainBoardScreen;
import org.aldar.bquest.util.Logger;
import org.aldar.bquest.util.TestUtil;
import org.andengine.entity.Entity;
import org.andengine.entity.modifier.*;
import org.andengine.entity.sprite.Sprite;

import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;

/**
 * User: Daria
 * Date: 5/31/13 6:38 PM
 */
public class AvailableMovesCounter {

    private static List<String> availableMoves;

    private static final Logger LOG = new Logger(AvailableMovesCounter.class);

    private static Sprite hintTile1 = null;
    private static Sprite hintTile2 = null;
    private static Sprite hintTile1Shadow = null;
    private static Sprite hintTile2Shadow = null;

    public static synchronized int checkAvailableMoves() {
        long millis1 = new Date().getTime();

        availableMoves = new LinkedList<String>();
        List<String> enemyKeys = new LinkedList<String>();
        for (int i = 0; i < IConstants.CELLS_HORIZONTAL; i++) {
            for (int j = 0; j < IConstants.CELLS_VERTICAL; j++) {
                int sourceCol = i;
                int sourceRow = j;
                String key = TileBoard.getKey(sourceRow, sourceCol);
                if (TileBoard.isCellValid(sourceCol, sourceRow)) {
                    TileSprite tile = TileBoard.getTileMap().get(TileBoard.getKey(sourceRow, sourceCol));
                    if (tile.getCurrentCol() != sourceCol) {
                        LOG.e("!!!!!!!!!!!!!! Current Col of tile does not match the key in the map!!! ");
                    }
                    if (tile.getCurrentRow() != sourceRow) {
                        LOG.e("!!!!!!!!!!!!!! Current Row of tile does not match the key in the map!!! ");
                    }
                    if (tile instanceof AbilityTileSprite) {
                        availableMoves.add(key);
                    }
                }
                if (TileBoard.isCellValid(sourceCol, sourceRow) && TileBoard.getTileMap().get(key).getEnemyImp() != null) {
                    enemyKeys.add(key);
                }
                int targetCol = i + 1;
                int targetRow = j;
                checkIsMoveEffective(sourceCol, sourceRow, targetCol, targetRow);
                targetCol = i;
                targetRow = j + 1;
                checkIsMoveEffective(sourceCol, sourceRow, targetCol, targetRow);
            }
        }
        TestUtil.getInstance().updateText("Moves", availableMoves.size() + " " + availableMoves);
        TestUtil.getInstance().updateText("Enemy tile keys", "" + enemyKeys);
        TestUtil.getInstance().updateText("Scene children", "" + ScreenContentManager.getScreenContentManager().getMainScene().getChildCount());

        LOG.i("loony Available moves: " + availableMoves);
        long millis2 = new Date().getTime();
        LOG.i("Check available moves ms: " + (millis2 - millis1));
        if (availableMoves.size() > 0) {
            prepareHint();
        }
        return availableMoves.size();
    }

    private static void prepareHint() {
        resetHints();
        if (hintTile1 != null) {
            hintTile1.detachSelf();
            TilesPool.pushEntityToStack(hintTile1);
        }
        if (hintTile2 != null) {
            hintTile2.detachSelf();
            TilesPool.pushEntityToStack(hintTile2);
        }
        if (hintTile1Shadow != null) {
            hintTile1Shadow.detachSelf();
            TilesPool.pushEntityToStack(hintTile1Shadow);
        }
        if (hintTile2Shadow != null) {
            hintTile2Shadow.detachSelf();
            TilesPool.pushEntityToStack(hintTile2Shadow);
        }

        hintTile1 = TilesPool.getEntityForTexture(ResourceManager.getInstance().getTipArrow());
        MainBoardScreen.getScm().getBonusLayer().attachChild(hintTile1);
        hintTile1.setVisible(false);
        hintTile1Shadow = TilesPool.getEntityForTexture(ResourceManager.getInstance().getTipShadow());
        MainBoardScreen.getScm().getBonusLayer().attachChild(hintTile1Shadow);
        hintTile1Shadow.setVisible(false);


        hintTile2 = TilesPool.getEntityForTexture(ResourceManager.getInstance().getTipArrow());
        MainBoardScreen.getScm().getBonusLayer().attachChild(hintTile2);
        hintTile2.setVisible(false);
        hintTile2Shadow = TilesPool.getEntityForTexture(ResourceManager.getInstance().getTipShadow());
        MainBoardScreen.getScm().getBonusLayer().attachChild(hintTile2Shadow);
        hintTile2Shadow.setVisible(false);


        hintTile1.setAlpha(0);
        hintTile2.setAlpha(0);
        hintTile1Shadow.setAlpha(0);
        hintTile2Shadow.setAlpha(0);

        String moveKey = availableMoves.get(new Random().nextInt(availableMoves.size()));
        Entity tile1Tile;
        Entity tile2Tile = null;
        if (moveKey.indexOf("_") >= 0) {
            String key1 = moveKey.substring(0, 2);
            String key2 = moveKey.substring(3, 5);
            Log.i("loony", "hint keys: " + moveKey + " " + key1 + " " + key2);
            tile1Tile = TileBoard.getTileMap().get(key1).getTile();
            tile2Tile = TileBoard.getTileMap().get(key2).getTile();
        } else {
            String key1 = moveKey;
            Log.i("loony", "hint keys: " + moveKey + " " + key1 + " ");
            tile1Tile = TileBoard.getTileMap().get(key1).getTile();
        }
        hintTile1.setVisible(true);
        hintTile1Shadow.setVisible(true);
        hintTile1.setPosition(
                TileSpriteUtil.getTileCenterX(tile1Tile.getX()),
                TileSpriteUtil.getTileCenterY(tile1Tile.getY() + 40));
        hintTile1Shadow.setPosition(
                TileSpriteUtil.getTileCenterX(tile1Tile.getX()),
                TileSpriteUtil.getTileCenterY(tile1Tile.getY()));
        hintTile1.registerEntityModifier(getHintModifier(hintTile1.getY()));
        hintTile1Shadow.registerEntityModifier(getHintShadowModifier());
        if (tile2Tile != null) {
            hintTile2.setVisible(true);
            hintTile2Shadow.setVisible(true);

            hintTile2.setPosition(
                    TileSpriteUtil.getTileCenterX(tile2Tile.getX()),
                    TileSpriteUtil.getTileCenterY(tile2Tile.getY()) + 40);
            hintTile2Shadow.setPosition(
                    TileSpriteUtil.getTileCenterX(tile2Tile.getX()),
                    TileSpriteUtil.getTileCenterY(tile2Tile.getY()));
            hintTile2.registerEntityModifier(getHintModifier(hintTile2.getY()));
            hintTile2Shadow.registerEntityModifier(getHintShadowModifier());
        }

    }

    private static IEntityModifier getHintShadowModifier() {
        return new SequenceEntityModifier(
                new DelayModifier(5f),
                new LoopEntityModifier(
                        new SequenceEntityModifier(
                                new AlphaModifier(0.4f, 0, 1),
                                new ScaleAtModifier(0.6f, 0.8f, 1f, 0.5f, 0.5f),
                                new ScaleAtModifier(0.6f, 1f, 0.8f, 0.5f, 0.5f),
                                new ScaleAtModifier(0.6f, 0.8f, 1f, 0.5f, 0.5f),
                                new ScaleAtModifier(0.6f, 1f, 0.8f, 0.5f, 0.5f),
                                new ScaleAtModifier(0.6f, 0.8f, 1f, 0.5f, 0.5f),
                                new ScaleAtModifier(0.6f, 1f, 0.8f, 0.5f, 0.5f),
                                new AlphaModifier(0.4f, 1, 0),
                                new DelayModifier(5f)
                        )
                )
        );
    }

    private static IEntityModifier getHintModifier(float y) {
        return new SequenceEntityModifier(
                new DelayModifier(5f),
                new LoopEntityModifier(
                        new SequenceEntityModifier(
                                new AlphaModifier(0.4f, 0, 1),
                                new MoveYModifier(0.6f, y, y - 10),
                                new MoveYModifier(0.6f, y - 10, y),
                                new MoveYModifier(0.6f, y, y - 10),
                                new MoveYModifier(0.6f, y - 10, y),
                                new MoveYModifier(0.6f, y, y - 10),
                                new MoveYModifier(0.6f, y - 10, y),
                                new AlphaModifier(0.4f, 1, 0),
                                new DelayModifier(5f)
                        )
                )
        );
    }

    public static void resetHints() {
        if (hintTile1 != null) {
            hintTile1.clearEntityModifiers();
            hintTile1.setVisible(false);
            hintTile1Shadow.clearEntityModifiers();
            hintTile1Shadow.setVisible(false);
        }
        if (hintTile2 != null) {
            hintTile2.clearEntityModifiers();
            hintTile2.setVisible(false);
            hintTile2Shadow.clearEntityModifiers();
            hintTile2Shadow.setVisible(false);
        }
    }

    private static void checkIsMoveEffective(int sourceCol, int sourceRow, int targetCol, int targetRow) {
        if (TileBoard.getTileMap().get(TileBoard.getKey(targetRow, targetCol)) == null || TileBoard.getTileMap().get(TileBoard.getKey(sourceRow, sourceCol)) == null) {
            return;
        }

        if (TileBoard.isCellValid(sourceCol, sourceRow) && TileBoard.isCellValid(targetCol, targetRow)) {
            TileBoard.swapInHashMap(sourceCol, sourceRow, targetCol, targetRow);
            if (MatchedTilesFinder.isTileInMatch(sourceCol, sourceRow) || MatchedTilesFinder.isTileInMatch(targetCol, targetRow)) {
                String key = TileBoard.getKey(sourceRow, sourceCol) + "_" + TileBoard.getKey(targetRow, targetCol);
                availableMoves.add(key);
            }
            TileBoard.swapInHashMap(sourceCol, sourceRow, targetCol, targetRow);
        }
    }

    public static void highlightAvailableMove() {
        for (String keys : availableMoves) {
            TileSprite sprite = TileBoard.getTileMap().get(keys.substring(0, 2));
            //sprite.getTile().setAlpha(0.1f * (5));
            sprite = TileBoard.getTileMap().get(keys.substring(3, 5));
            //sprite.getTile().setAlpha(0.1f * (5));
        }
    }


}
